Standard ML Weak Polymorphism Can Be Sound

نویسنده

  • John Greiner
چکیده

Adding ML-style references to a Hindley-Milner polymorphic type system is troublesome because such a system is unsound with naive polymorphic generalization of reference types. Tofte [12] introduced a distinction between imperative and applicative type variables, such that applicative type variables are never in reference types, that provides a simple static analysis of which type variables may be polymorphically generalized. MacQueen's [7] weak type variables generalize imperative type variables with a counter called a strength. The ner distinction allows a more accurate analysis of when a reference may be created, and thus which type variables may be generalized. Unfortunately, weak polymorphism has been presented only as part of the implementation of the SML/NJ compiler, not as a formal type system. As a result, it is not well understood, as its more subtle points are not well known. Furthermore, while versions of the implementation have repeatedly been shown unsound, the concept has not been proven sound or unsound. We present several formal systems of weak polymorphism, show their connection to the SML/NJ implementation, and show the soundness of most of these systems. 1. Background A reference cell is an assignable memory location and is a primary imperative feature of Standard ML of New Jersey (SML/NJ). The language is unsound if reference types are polymorphically generalized in the usual manner of the Hindley-Milner type system. For example, a list of integers could be stored in the cell, and a list of booleans read from it, as in the expression let val a = ref nil in a := [1]; not (hd(!a)) end While it is unsound to polymorphically generalize types of the form ref, generalizing function types involving references is not necessarily so. A simple example is let val ref' = fn x => ref x in (ref' 1,ref' true) end A number of type systems have been proposed to allow code such as this while preserving soundness [1, 4, 6, 10, 11, 13]. Of particular interest for this paper are those of Tofte [12] and MacQueen [7]. In the standard Hindley-Milner type system, generalization is allowed on all free type variables not occurring in the (variable) type assumption, a mapping from variables to type schemes. However, with references, it is also necessary to have a location type assumption, assigning a type to each location of the store [12]. The unsoundness of the naive static semantics is a result of generalizing type variables occurring free in the location type assumption [12]. Since neither the store nor the location type assumption can be known statically, a safe approximation must be made to determine those type variables which may occur in the location type assumption and therefore should not be generalized [12]. In order to provide such a safe approximation, Tofte introduces a distinction between two classes of type variables, called applicative and imperative. Imperative type variables are used to statically track values that may be placed in reference cells. Applicative type variables are not used with reference types and can always be polymorphically generalized. Additionally, imperative type variables can be generalized if the evaluation of the let-bound expression does not lead to the creation of a reference cell. Since this is undecidable, Tofte de nes an expression to be non-expansive if it is syntactically a value other than a reference cell. The second example above is then type correct. Since functions are non-expansive, the local type assumption maps ref' to the type scheme 8 u.u -> u ref, where u is imperative, which instantiates to both int -> int ref and bool -> bool ref. The rst example is still rejected as desired since the expression ref true is not non-expansive, and its type is not generalized. However, this static analysis is overly conservative. In the example let val ref2 = fn x => fn y => ref x in let val ref1 = ref2 nil in (true :: !(ref1 ()),1 :: !(ref1 ())) end end the type of ref1 is not generalized because application expressions are considered expansive. Since there is no generalization, the expression does not have a type since ref1 cannot be of type unit -> bool ref and unit -> int ref. However, it is sound to allow such code since a di erent reference cell is created for each call. One method to improve upon Tofte's system is to track not only which values may be placed in reference cells, but when the cells are created. This additional information can then be used for a more accurate de nition of non-expansiveness. This is the essence of MacQueen's weak polymorphic types. 1 2. Weak Polymorphic Types Weak polymorphism expands on Tofte's distinction of type variables. To produce a better static analysis of what values may be in reference cells, type variables are indexed by an integer, known equivalently as its strength or weakness. A strength s of a type variable in the type of an expression indicates that during the evaluation of the expression supplied with less than s arguments, no cell is created of a type involving that type variable. Applicative type variables correspond to those of in nite strength, whereas those of nite strength are weakly polymorphic. In particular, a type variable with strength of zero corresponds to the possible creation of a cell with a type involving that type variable during the evaluation of the expression. Non-critical type variables, those of positive strength, are generalized, but critical variables are not. Thus the improvement over Tofte's system stems from being able to generalize some imperative or weak variables. This is similar to Tofte's non-expansive condition for allowing generalization. A more in-depth comparison of the two related systems in found in Section 7. Using such motivation, we can develop the basic ideas of weak types. Since a reference cell must have a critical type, ref nil : '0a list ref and purely functional terms have types of in nite strength.1 fn x => x : 'a -> 'a Abstraction increments strengths, since they count the number of applications until a reference is created. fn x => ref nil : 'b -> '1a ref fn x => ref x : '1a -> '1a ref Similarly, application decrements the strengths in the function position. (fn x => ref x) nil : '0a list ref If the argument of an application has a weak type, the analysis must make a conservative approximation. In general, the function may in turn apply its argument to multiple arguments, where each application corresponds to a decrement in strengths. Statically, the conservative assumption is made that enough applications are performed for a reference cell to be produced. For example, the strength of 'a in (fn x => fn y => ref x) : '2a -> 'b -> '2a ref must be made critical when the expression is used as an argument in (fn f => f nil nil) (fn x => fn y => ref x) : '0a list ref Following the previous examples, the following code would be assigned a type with negative strength ((fn f => f nil) (fn x => fn y => ref x)) nil : '~1a list ref since the application to nil decrements the already critical strengths of the function. SML/NJ avoids negative strengths at the top-level in most cases. But in Version 0.66, which follows this motivation closely, (let val x = ref (fn z => z) in fn y => x end) () : ('~1a -> '~1a) ref Intuitively, the let expression has type unit -> ('0a -> '0a) ref since a reference is created, and the application decrements the strengths one more. More commonly, negative strengths are only used when type checking sub-expressions of the original expression as in 1In SML/NJ, in nite strengths are not printed. 2 ref (fn z => z) : ('0a -> '0a) ref The strength of 'a when type checking z can be thought of as being ~1, which is then incremented by the abstraction. Weak polymorphism has been developed by MacQueen within the type inference algorithm of SML/NJ. Only this algorithm has served as the de nition of the type system, and unfortunately, numerous implementations have been shown to be unsound. Each has had problems which could be ascribed to implementation details, but the concept has not been proven sound. Additionally, key ideas of the algorithm, such as this conservative approximation at application, have not been widely known, so the system has been poorly understood even by skilled SML/NJ programmers. This paper addresses these problems. In Section 3, this motivation is transformed into a formalism, the soundness of which is outlined in Section 4 and given in full in the Appendix. In Section 5, it is shown how this formalism relates to a more algorithmic formalism, which is also sound. Other details of a comparison to the algorithm of SML/NJ are presented in Section 6, and a comparison to other approaches is in Section 7. 3. A Declarative Formalism { This section presents a formal de nition of an ML-like language, related to the previous motivation of weak polymorphism. This includes the rules and motivation for the syntax, dynamic semantics, and static semantics, as well as the notation used in the semantics and proof. The expression language used is de ned by x 2 variables l 2 locations e 2 expressions ::= x j l j () j ref e j !e j e1:=e2 j let x=e1 in e2 j e1 e2 j fn x) e v 2 values ::= l j () j fn x) e The free variables of the expression, FV(e), are de ned in the usual manner. Capture-avoiding expression substitution is denoted [e0=x]e. An empty mapping is denoted by , while the extension of a mapping over an additional domain element is denoted like X[d 7! r].2 Mappings are also abbreviated like [d1 7! r1; . . . ; dn 7! dn]. The union of disjoint mappings is written as X;X 0. Dynamic Semantics The dynamic semantics is de ned by the following standard rules, where a memory is a nite mapping between locations and values. The judgment ` e =) v; 0 is well-formed if e is closed with respect to all variables, and reads \Given the memory , the expression e evaluates to v, resulting in a new memory 0." ` v =) v; (VAL) ` e =) v; 0 ` ref e =) l; 0[l 7! v] if l 62 dom( 0) (ALLOC) 2Except for type assumptions, written like [x : ]. 3 ` e =) l; 0 ` !e =) 0(l); 0 (CONT) ` e1 =) l; 1 1 ` e2 =) v; 2[l 7! v0] ` e1:=e2 =) (); 2[l 7! v] (UPD) ` e1 =) fn x) e01; 1 1 ` e2 =) v2; 2 2 ` [v2=x]e01 =) v; 0 ` e1 e2 =) v; 0 (APPLY) ` e1 =) v1; 1 1 ` [v1=x]e2 =) v2; 2 ` let x=e1 in e2 =) v2; 2 (BIND) Static Semantics The types and type schemes are de ned by s; a;w 2 strengths = Z [ f1g ; 2 tyvars 2 types ::= j unit j 1! 2 j ref 2 typeschemes ::= 8 : where a strength context is a nite mapping from type variables to strengths. The trivial type scheme 8 : is abbreviated by . Since all instances of a type variable in a type or type scheme must have the same strength, strength contexts are used to maintain consistency. The free (bound) type variables of a type or type scheme are denoted by FTV( ) (BTV( )). These functions are also extended to location and variable type assumptions, and are also extended to be n-ary functions so that, for example, FTV( ; ) = FTV( ) [FTV( ). Type variables of non-positive strength are critical, or Crit (A), if for all 2 A, ( ) 0. Similarly, NonCrit (A), if for all 2 A, ( ) > 0. A type is (non-)critical relative to if all of its type variables are (non-)critical in . Weaker (A; s) holds if for all 2 A, ( ) = 1 or ( ) s, and similarly, SWeaker (A; s) holds if for all 2 A, ( ) s. Let ( + c)( ) = ( ) + c. The minimum of two strength contexts having the same domain, min( 1; 2), is de ned by the point-wise minimum. A strength context 0 is weaker (below s) than strength context of the same domain, 0 s , if for all 2 dom( 0), 0( ) = ( ) whenever ( ) s, and otherwise 0( ) ( ). Of particular interest is the case when s = 1, which implies that the two strength contexts agree on all positive strengths, but that 0 is more critical than . Note that 0 + 1 s + 1 implies 0 s , which implies 0 s+1 , but the converses do not hold. Instantiation is de ned much as it is in the standard Hindley-Milner type system, but with restrictions on weak type variables. A type scheme instantiates to a type, ` 8[ 1 7! s1; . . . ; n 7! sn]: 0 if there exists a type substitution S = [ 1 7! 1; . . . ; n 7! n] such that S( ) = 0, and for all 2 FTV( i), ( ) si. Similarly, relative to , a type scheme 0 is more general than , written ` 0 , if for any type such that ` , then ` 0 . For example, for any j < i, ` 8[ 7! i]: ! 8[ 7! j]: ! 4 but not ` 8[ 7! j]: ! 8[ 7! i]: ! and the type schemes 8[ 7! j; 7! i]: ! and 8[ 7! i; 7! j]: ! are incomparable. A type judgment ; ` e : reads \With strength context , given the location type assignment and variable type assignment , e has type ." Such a judgment is well-formed if dom( ) FTV( ; ; ) and this relation. Derivability is de ned by the following rules which use the de nitions in the remainder of this section. ` (x) ; ` x : (VARD) (l) = ; ` l : ref (LOCD) ; ` () : unit (UNITD) ; ` e : ; ` ref e : ref if Crit (FTV( )) (REFD) ; ` e : ref ; ` !e : (!D) ; ` e1 : ref ; ` e2 : ; ` e1:=e2 : unit (:=D) ; ` +1 e1 : 2! ; ` e2 : 2 ; ` e1 e2 : if Weaker (FTV( 2); 0) (APPD) ; [x : 1] ` 1 e : 2 ; ` fn x) e : 1! 2 if x 62 dom( ) (LAMD) ; ` ; 0 e1 : 1 ; [x : 8 0: 1] ` e2 : 2 ; ` let x=e1 in e2 : 2 if x 62 dom( ), NonCrit 0(dom( 0)), and Weaker ((FTV( 1) \ dom( )) FTV( ; );0) (LETD) Note that the strengths are incremented and decremented in (APPD) and (LAMD). The side condition of (APPD) enforces the conservative approximation previously described. The side condition on (REFD) simply re ects the usual treatment of ref as a functional primitive having the type scheme 8[ 7! 1]: ! ref. In (LETD), and 0 have disjoint domains by the de nition of the map union operator. So, by the well-formedness of the second precondition, the domain of 0 is disjoint from the free type variables of both type assumptions. By using the strength context 0 only in the rst subderivation, it is explicit that the names of the generalized type variables are relevant only locally. The last side condition of (LETD) states that any nitely positive type variables in 1, but not in the 5 type assumptions, must be generalized. Without this restriction, the following judgment is derivable. ; `[ 7!2] let x=fn z ) fn y ) ref y in x() : ! ref This is a very technical condition. It disallows the rule's use if any type variable in (FTV( 1)\FTV( 2)) FTV ; is nitely positive in . But, if this were the case, there exists another derivation to allow the let expression to type by renaming these type variables in 1 with fresh type variables, and adding them to 0. To relate the locations in the dynamic and static semantics, a memory type matches (with respect to ) the type context , or ` : , if dom( ) = dom( ), if for all l 2 dom( ), ; ` (l) : (l). 4. Soundness This section presents an overview of the soundness proof of the formalism, including the statement and proof sketches of the theorem and main lemmas. For the full proof, refer to the Appendix. Soundness is shown by proving a form of type preservation under evaluation, as in [2, 3, 12, 15]. The theorem and lemmas are similar to those for the functional Hindley-Milner and Tofte's imperative type systems, except that extra conditions are needed to keep tight control on the strengths of pertinent type variables. Unfortunately, while evaluation preserves types, it does not necessarily preserve strengths. For example, consider the following expressions: e0 = fn z ) z e1 = fn x) fn y ) x e0 e0 e2 = fn a) (let b=ref a in fn c) !b)() e = e1 e2 v = fn y ) e2 e0 e0 In particular, e2 is a function which is assigned a critical type, and e evaluates to v. The strongest typings for e and v are ; `[ 7!0; 7!1] e : ! ! ; `[ 7! 1; 7!1] v : ! ! It is sound to assign the stronger type to v, but the analysis provided by the formalism is not able to give this stronger type. As will be proved, no such example exists for non-critical types. This does not entirely contradict the usual intuition that if e evaluates to v, then v could be given a more general type than e. In most cases, v could be assigned the same or higher strengths. For a simple example, consider e = (fn x) x)(fn y ) ref y) v = fn y ) ref y Since ; `[ 7!0] e : ! ref, the Type Preservation theorem states that there exists a critical strength s such that ; `[ 7!s] v : ! ref. But, in fact, v can be typed with the higher strength context [ 7! 1]. The Top-Level Type Preservation theorem states that if e evaluates to v, then e and v have the same type, although v may require more critical strengths. Furthermore, any cells created during this evaluation have critical types. Theorem (Top-Level Type Preservation Under Evaluation) If ` e =) v; 0 and ; ` e : , then there exists 0, and 0 1 such that 0; ` 0 v : , ` 0 0 : 0, and Crit 0(FTV( 0)). 6 Proof Sketch: This is proved by generalizing the theorem to all location type assumptions, and generalizing the strength context, and then by structural induction on the evaluation derivation. The (APPLY) and (BIND) cases require the following Value Substitution lemma. The last assumption of that lemma is achieved through the side conditions on the (APPD) and (LETD) rules. The rest of the cases are not di cult, although extensive use is made of the Weakening and Strengthening lemmas. 2 The Value Substitution lemma states that, under restrictions, the type of an expression is stable under substitution of a value for a variable of more general type. The result of the substitution may require more critical strengths. Lemma (Value Substitution) If ; ` ; 1 v : 1, ; [x : 8 1: 1] ` e : 2, dom( ) dom( ), and Weaker (FTV( ; 1) \ dom( );0), then there exists 0 1 such that ; ` 0 [v=x]e : 2. Proof Sketch: This lemma must also be generalized to allow a proof by structural induction on the type derivation of e. In general, the strength context for the second assumption is of the form ( ; 2) + c, and for the conclusion, ( 0; 2)+ c. The strength context 2 accounts for the local type variables in the (LETD) case, which cannot be allowed to decrease. The constant c generalizes the constant 1 or 1 added in the (APPD) and (LAMD) cases. Because of the generalization, the only interesting case is when e = x, which is proved as an instance of the following Type Substitution lemma and Weakening. 2 Lemma (Type Substitution) If ; ` ; 1 e : , S = [ 1 7! 1; . . . ; n 7! n], for all 1 i n, SWeaker( ; 2)+c(FTV( i); 1( i)), Weaker (FTV( ; ; ) \ dom( ); 0), then there exists 0 1 such that S( );S( ) `( 0; 2)+c e : S( ). Proof Sketch: As with Value Substitution, the strength contexts are generalized so that the resulting lemma may be proved by structural induction on the type derivation. In particular, the rst assumption uses ( ; 1; 0) + c0, and the conclusion uses ((( 0; 2) + c); 0) + c0. The (VARD) base case is then proved by nding an appropriate 0 such that the required instantiation holds. Similarly, the (REFD), (APPD), and (LETD) cases require calculating an an appropriate 0 such that the side conditions hold, as well as using the Ground Type Substitution lemma to eliminate some type variables from consideration. The remaining cases follow easily. 2 There are several other lemmas to strengthen and weaken type derivations. The previously mentioned Ground Type Substitution proves that any type derivations are stable when type variables are consistently replaced by ground types. Strengthening states that unused variables may be discarded from the variable type assumption and strength context. And Weakening shows that extra assumptions are allowed in the location and variable type assumptions and the strength context, and that the nite strength numbers may be safely decreased. In particular, does not allow in nite strengths to be decreased arbitrarily. For example, ; `[ 7!c; 7!1] fn f ) fn x) fx : ( ! )! ! only if c =1 or c 2. 7 5. Algorithmic Formalisms The implementation of SML/NJ does not use this motivational formalism. While similar, one of its core ideas is the use of an occurrence which approximates the surrounding syntactic context of a subexpression. The \top-level" occurrence is named Root, and the mappings on occurrences are named Rator( ), Rand( ), Abs( ), and Let( ), on application functions, application arguments, abstraction bodies, and let-bound expressions, respectively. Various versions of SML/NJ include di erent elds in occurrences, and the remainder of this paper discusses the two primary ones, while other features not used are discussed in Section 6. The Systems and Instead of incrementing and decrementing every strength in the context at every abstraction and application, a single o set can be used. This o set, called the abstraction depth, is the rst eld of an occurrence. Thus, we can split the strength context into a strength context and an abstraction depth a such that = a, and the typing rules can be written leave xed. The abstraction depth of a given subsexpression approximates the number of times that subexpression is applied in the whole expression. The only e ect of making such a change is an increase in e ciency. In order to motivate the other eld used here, we digress temporarily. A more restrictive version of the typing rule for applications would be ; ` +1 e1 : 2! ; ` e2 : 2 ; ` e1 e2 : if Weaker (FTV( ; ; 2); 0) (APP0D) The type system resulting from replacing (APPD) with (APP0D) is sound since it is a (strict) subsystem of the original. Surprisingly, however, the Value Substitution lemma does not hold in . For example, let v = fn a) a()()() e = fn y ) let u=ref y in x so that they are assigned non-critical types ; `[ 7!1] v : (unit!unit!unit! )! ; [x : (unit!unit!unit! )! ] `[ 7!1; 7!1] e : !(unit!unit!unit! )! but the result of substitution is typed as ; `[ 7!1; 7!0] [v=x]e : !(unit!unit!unit! )! where a non-critical strength has been lowered. As a result, the soundness of this system cannot be shown directly using the same style of proof as in Section 4. Use of the second component of the occurrence, the maximum weakness w, allows the side condition on (APP0D) to be replaced by a check at instantiation. For this system, there is no reason to prefer this alternative, although some motivation will be given for other systems. The maximum weakness is an upper bound on nite strengths in . The mappings on occurrences (a;w) are then de ned by Rand(a;w) = (a;min(a;w)) Rator(a;w) = (a 1;w) Abs(a;w) = (a + 1;w) Let(a;w) = (a;1) Root = (0;1) 8 A type judgment ; ` ;a;w e : reads \With strength context , at the occurrence containing the abstraction depth a and maximum weakness w, and given the location type assignment and variable type assignment , e has type ." Such a judgment is well-formed if dom( ) FTV( ; ; ). Derivability in is de ned by the following rules. ` a (x) ; ` ;a;w x : if Weaker (FTV( ; ; );w) (VARA) (l) = ; ` ;a;w l : ref if Weaker (FTV( ; );w) (LOCA) ; ` ;a;w () : unit if Weaker (FTV( ; );w) (UNITA) ; ` ;Rand(a;w) e : ; ` ;a;w ref e : ref if Crit a(FTV( )) (REFA) ; ` ;a;w e : ref ; ` ;a;w !e : (!A) ; ` ;a;w e1 : ref ; ` ;a;w e2 : ; ` ;a;w e1:=e2 : unit (:=A) ; ` ;Rator(a;w) e1 : 2! ; ` ;Rand(a;w) e2 : 2 ; ` ;a;w e1 e2 : (APPA) ; [x : 1] ` ;Abs(a;w) e : 2 ; ` ;a;w fn x) e : 1! 2 if x 62 dom( ) (LAMA) ; ` ; 0 ;Let(a;w) e1 : 1 ; [x : 8 0 a: 1] ` ;a;w e2 : 2 ; ` ;a;w let x=e1 in e2 : 2 if x 62 dom( ), NonCrit 0 a(dom( 0)), and Weaker ((FTV( 1) \ dom( )) FTV( ; );a) (LETA) Only the abstraction depth is incremented and decremented in (APPA) and (LAMA). But, the strength context o set by the abstraction depth is now used in (VARA), (REFA), and (LETA). Since Let(a;w) = (a;1), (LETA) places no upper bound on the strengths of the type variables in 0. The strengths in are still bound by the maximum weakness w in the type derivation of e2. If instead Let(a;w) = (a;w), then there would be no generalization in expressions such as f (let x=fn z ) ref z in e). Similarly, the top-level occurrence Root also has an in nite maximum weakness, so that no extra constraints are placed on strengths. By structural induction, it is easy to show that Lemma (Maximum Weakness { ) If ; ` ;a;w e : , then Weaker (FTV( ; ; );w). In particular, this implies that the side condition of (APP0D) is satis ed by this system, also. Thus it is easy 9 to show by induction that Lemma ( Contains ) If ; ` ;a;w e : , then ; ` a e : . In fact, these two systems are equivalent, in the sense that they admit the same derivations at the \top-level". This follows from Lemma ( Contains ) If ; ` a e : , and Weaker (FTV( ; ; );w), then ; ` ;a;w e : which is proved by structural induction, and using Ground Type Substitution. The System The SML/NJ implementation is not as restrictive in its use of the maximumweakness. The following changes result in a system, , more like and the implementation. ` a (x) ; ` ;a;w x : if Weaker (FTV( );w) (VAR0A) (l) = ref ; ` ;a;w l : (LOC0A) ; ` ;a;w () : unit (UNIT0A) For this system, it might be argued that the side condition of (VAR0A) is more e cient than that of (APPD) since instantiation must examine the strengths of some of the type variables of anyway. This system is strictly less conservative than and , but is incomparable with . For example, if e = (fn z ) z)(fn a) let x=fn y ) ref a in fn b) ref b) then in we have ; `[ 7!2; 7!0];Root e : ! ! ref. But, in , the nite strengths of the argument must be critical, so is at most 0. And if e = (fn z ) (fn x) fn y ) z)(z:=fn a) ref a)())(ref (fn a) ref a)) then in we have ; `[ 7!0] e : ! ref. But, in , can only have strength 1 at the occurrence Root. It can be shown, however, that an expression typable in is also typable in at the top-level occurrence by only lowering critical strengths. As a result, the soundness of this system is still open, as is its stability under substitution. One factor that complicates proofs is that only very weak forms of a MaximumWeakness lemmahold as in the following. Lemma (Maximum Weakness { ) If ; ` ;a;w e : 1! ! n, then Weaker (FTV( n);w). The Systems + and + The conservative approximation at application in all of the previous systems is overly conservative. As motivated, the nite strengths of the argument type must be critical, because the function may, in turn, 10 apply its argument to other arguments, possibly creating a reference cell. If the argument is purely functional, however, this is impossible. But by using the same strength context (modulo a constant o set) to type both the function and argument, this cannot always be detected. For example, in , ; `[ 7!0; 7!1] (fn x) fn y ) ref x)(fn a) a) : !( ! ref) Here, the argument, the identity function, must be given a weak type to match the strength of the function domain. The following more complicated application rule does not force the conservative approximation on the type variables of the argument which \could have been" of in nite strength. ; ` +1 e1 : 2! ; ` 0 e2 : 2 ; ` e1 e2 : if Weaker 0(FTV( 2);0), and 0( ) ( ) if 2 FTV( 2) FTV( ; ) 0( ) = ( ) otherwise (APP00D) This e ectively makes part of uni cation explicit in the formalism. The system +, using this application rule, is strictly less conservative than . The soundness proof extends to this system with little modi cation only if a weakening rule such as the following is also included. ; ` e : ; ` 0 e : if 0 (WEAKEND) where 0 if 0 is point-wise less than or equal to . Because of the Weakening lemma, it would be su cient for the side condition to state that and 0 aggree on all nite values in . Without such a rule, the system is not stable under substitution, but still might be sound. This weakening rule is only useful immediately preceding application, so the typing rules could be combined. This would restore the syntax-directedness of the system, but would further complicate the side conditions on the application rule. The algorithmic system + can be de ned similarly, and is the most SML/NJ-like system in this paper. Like , however, its soundness is still open. 6. Relation to SML/NJ Some di erences between SML/NJ and the formalisms are primarily syntactic. First, SML types correspond to the pairing of types and strength contexts. And unlike SML, the formalisms restrict the reference primitives to their fully applied forms. It would be equivalent to replace the inference rules for the reference primitives with the following ref : 8[ 7! 1]: ! ref ! : 8[ 7! 1]: ref! := : 8[ 7! 1]: ref! !unit in the variable type assumption, or as the equivalent axioms. The disadvantage of this alternative is that values must be given to the evaluation of partially applied primitives, which complicates the dynamic semantics and loosens the correspondence of the inference rules of the static and dynamic semantics. However, the algorithmic formalisms are slightly stronger than the implementation in that the type inference rules for ! and := do not use Rand( ) as does general application. This is safe since these primitives are known not to create any cells when partially applied. The implementation implicitly uses (WEAKEND) when unifying types in the application case. It was omitted from the majority of the formalisms because its non-syntax-directed nature complicates proofs. Or, 11 if combined with the application rule of each system, it would hinder comprehension. The systems are sound, and admit more types for expressions, but apparently do not type more expressions with its addition. Sequencing, e1; e2, can be treated as syntactic sugar for let z=e1 in e2, where z is new. The type inference rule in the declarative framework would be ; ` e1 : 1 ; ` e2 : 2 ; ` e1; e2 : 2 (;D) In the declarative formalisms, either de nition of sequences admits the same expressions to be typed, although the de nition as a let expression allows more derivations. Also, the implementation has three additional elds in the occurrence. The lambda depth is similar to the abstraction depth, but is not decremented in Rator( ). Its use seems to be to prevent function expressions from being given critical types (except when the function is used as an argument, of course). In later versions, the base eld provides a simpler, but unsound, analysis which allows (let val x = ref (fn z => z) in fn y => x end) () : ('1a -> '1a) ref It is unclear how either of these relate to the declarative formalisms. The outer eld allows curried function applications to be treated somewhat like a single uncurried application, by using the same occurrence for each of its arguments. This corresponds to having a single application rule for typing multiple curried arguments at once, as in ; ` +n e0 : 1! n! ; ` ei : i ; ` e0 e1 . . . en : if Weaker (FTV( i);0), for all 1 i n (APP manyD) Because of side e ects, the implementation e ectively does not use the same strength context when type checking multiple antecedents of an inference rule. For example, when type checking the following expression, the implementation decrements the same strength counter for each application f(). fn a => let val f = fn b => fn c => ref a in f(); f(); f() end : '0a -> 'c -> '0a ref However, the formalisms allow the expression to have the type ! ! ref, with the expected strength, ( ) = 2. 7. Comparisons with Other Related Systems Weak polymorphism is often explained as it is here, as a generalization of Tofte's imperative type system, but this is not entirely correct. Tofte's system uses two inference rules for type checking let expressions. One generalizes all type variables when the let-bound expression is non-expansive. The other generalizes applicative type variables when the expression is expansive. If an expression of critical type were necessarily expansive, then the let type inference rule would subsume both cases, but this is not so. For example, in the declarative systems, ; ` 7!s fn a) (let x = ref a in fn y ) x)() : ! ref only if s 0. Thus, the expression is of critical type, but non-expansive. Thus, we conjecture that restricting any of the formalisms to using only the strengths 0 and 1,3 and augmenting it with Tofte's non-expansive let type inference rule is strictly more powerful than Tofte's system. 3Where 0 n = 0, 0 + n = 0, and 1 n = 0, for any n. 12 Hoang, Mitchell, and Viswanathan [4] proved the soundness of a di erent type system based on weaktypes. They permit di erent strengths on separate instances of a type variable in a type as infn f => f nil : ('sa list -> 'sa) -> '(s 1)afor any nite strength s. The decremented strength of the function result re ects the single application in thefunction body. This generalization of the SML/NJ approach gives a more informative analysis of strengths,even for purely functional terms as above, which eliminates the need for the conservative approximationof strengths at function applications. As a result, they claim that their system is more general than thatof SML/NJ and provide empirical evidence of this, but they lack a formalization of SML/NJ to prove theclaim.In their analysis of reference creation, both weak and imperative types label type variables with infor-mation. Another approach is to label type arrows with e ects, an approximation of the change in the store.The static semantics then derives both a type and an e ect for an expression, and generalization is thende ned relative to those e ects. This approach is taken by Damas [1], Leroy and Weis [6], Reynolds [9],Talpin and Jouvelot [10, 11], and Wright [13]. A slightly di erent approach is given by Leroy [5], where typearrows are labelled with types that may occur in references. He also provides a comparison of this approachwith some of these others.For a comparison of some of these systems to each other, see Wright [13]. Also refer to O'Toole [8] fora rough comparison of four systems, including MacQueen's.4 In general, this approach appears to be morepowerful than weak types, although existing systems are incomparable. Furthermore, the systems using thisapproach have simpler inference rules than those shown here for weak polymorphism. However, in practicethe approach may be unwieldy, because of the size of the type arrow labels.Weak polymorphic types may be examined with this approach as well. As a rough outline, the types arede ned as::= j unit j E!::= 8 1; . . . ; n:where E is a set of type variables with the restriction that in the type 1 E1!En+1! n, if 2 Ei, then2 Ei+1. (Unfortunately, we see no obvious motivation for this restriction in this setting.) Then the type= 1! ! n in the strength context corresponds to the type 1 E1!En 1! n paired with the e ectE0, where Ei = f j 2 FTV( ); ( ) ig. The following table gives some examples of the correspondenceto SML/NJ types:'0a refref, f g'1a -> '1a ref! ref, ;'2a -> 'b -> '2a ref! ! ref, ;('2a -> '0c) -> '1b -> '2a( ! ) ! ! , f gWright [14] suggests that all of these systems are too complex for a practical type system, particularlyin combination with modules. He notes that generalization is always sound if restricted to values, and givesempirical evidence that this restriction is not a great sacri ce in programming exibility.4O'Toole incorrectly allows generalization of critical type variables in his formalization of weak polymorphism.13 8. Conclusions and Future WorkWe have motivated and described several formalisms of weak polymorphic types which are quite similar tothat of SML/NJ. In particular, the algorithmic family of calculi closely model the details of the implementa-tion. Most of these have been proven sound with respect to the standard call-by-value operational semantics.Naturally, any of these could be incorporated into SML/NJ, to restore proven soundness to its type system.But, since weak polymorphism is also used to type continuations and exceptions, it should be veri ed thatextending the system with these features is sound, although no complications are expected. The soundnessof the remaining formalisms, and+, should also be determined, since they are closely related to theimplementation.Despite the similarities to SML/NJ, detailed comparisons are still somewhat di cult because the im-plementation has a broader de nition of occurrences, and it uses side e ects. The family of formalismscould be enriched with the more general de nition of an occurrence to further study some of these details.We conjecture that using the lambda depth eld allows more function expressions to be non-critically typed,but still does not allow the type preservation theorem to hold without using more critical strengths.These systems should be systematically compared to the alternate formalization of weak types foundin [4]. This would test the claim that their approach is strictly more general than that of SML/NJ. It alsoprovides a potential method of proving the soundness of and+, should their system be more generalthan these two calculi.Many of the side conditions in the type rules are complex. This is especially true of the more powerfulapplication rules, which more closely model the implementation. Since simplicity is one goal of a typesystem, so that it can be easily understood by the programmer, this points to a fundamental problem ofpracticality for the approach of weak polymorphism.The connection between type systems which label type variables and those which label type arrowsshould also be further explored. Since speci c systems of these two approaches are generally incomparablein power, it may be worthwhile to somehow combine the ideas in one system. However, such a combinationwould likely result in types too cumbersome in practice.AcknowledgmentsMany thanks go to Robert Harper, Mark Lillibridge, and the two anonymous referees of JFP for their manyhelpful ideas. I would also like to thank Peter Lee and Mark Leone for their comments.References[1] L. Damas. Type Assignment in Programming Languages. Ph.D. Thesis, University of Edinburgh. April,1985.[2] Robert Harper. A Simpli ed Account of Polymorphic References. Unpublished manuscript. April, 1992.[3] J. Roger Hindley, Jonathan P. Seldin. Introduction to Combinators and -Calculus. Cambridge Univer-sity Press, London Mathematical Society Student Texts, Volume 1. 1986.[4] My Hoang, John Mitchell, Ramesh Viswanathan. Standard ML weak polymorphism and imperativeconstructs. In 8th Symposium on Logic in Computer Science. pp. 15{25. IEEE Computer Society Press.[5] Xavier Leroy. Polymorphic Typing of An Algorithmic Language. Ph.D. Thesis, University Paris VII.Technical Report 1778, Institute National de Recherche en Informatique et en Automatique. October,1992.14 [6] Xavier Leroy, Pierre Weis. Polymorphic type inference and assignment. In ACM Symposium on Princi-ples of Programming Languages, pages 291{302. 1991.[7] Dave MacQueen. Source code for SML/NJ type inference algorithm.[8] James WilliamO'Toole, Jr. Type Abstraction Rules for References: A Comparison of Four Which HaveAchieved Notoriety. Technical report MIT{LCS{TM{390, MIT. 1989.[9] John C. Reynolds. Syntactic Control of Interference, Part 2. In International Colloquium on Automata,Languages, and Programming, pages 704{722. July, 1989.[10] Jean-Pierre Talpin, Pierre Jouvelot. The Type and E ect Discipline. In 7th IEEE Symposium on Logicin Computer Science. pp. 162{173. IEEE Comput. Soc. Press. 1992.[11] Jean-Pierre Talpin, Pierre Jouvelot. Polymorphic Type, Region and E ect Inference. In Journal ofFunctional Programming, Vol. 2, No. 3. pp. 245{271. Cambridge University Press. 1992.[12] Mads Tofte. Operational Semantics and Polymorphic Type Inference. Ph.D. Thesis, University of Edin-burgh. 1988.[13] Andrew K. Wright. Typing References by E ect Inference. In European Symposium on Programming,Lecture Notes in Computer Science, volume 582. pp. 473{491. February, 1992.[14] Andrew K. Wright Polymorphism for Imperative Languages without Imperative Types. Technical Report93{200, Rice University. February, 1993.[15] Andrew K. Wright, Matthias Felleisen. A Syntactic Approach to Type Soundness. Technical Report91{160, Rice University. July, 1991.Appendix { ProofThis appendix presents the proofs of the soundness theorem and lemmas for system , as outlined inSection 4. They are presented in the order of their dependence.Lemma 1 ( -Renaming Type Substitution) If; ` e : ,S = [ 1 7!01; . . . ; n 7!0n],dom(S) dom( ), andrng(S) \ dom( ) = ;,then S( );S( ) `S( ) e : S( ).Lemma 2 (Ground Type Substitution) If; ` e : ,S = [ 1 7! 1; . . . ; n 7! n], where01; . . . ;0n are distinct from each other,dom(S) dom( ), andFTV(rng(S)) = ;,then S( );S( ) ` e : S( ).15 These two lemmas are special cases of type substitutions. The rst one is used to show that the namesof generalized variables can be -renamed to avoid con icts with other strength contexts. The second isused to eliminate unnecessary type variables from consideration. Both follow easily by structural inductionon the type derivation. See the proof of Type Substitution for details of the (VARD) case.Lemma 3 (Weakening) If; ` 0 e : ,00 1 0,FTV( 0; 0) dom( 0; 1),dom( ) \ dom( 0) = ;, anddom( ) \ dom( 0) = ;,then ; 0; ; 0 `00; 1 e : .Several subcases of this weakening lemma are used. It is proved by structural induction on the typederivation, using -Renaming Type Substitution in the (LETD) case to rename type variables in the domainof 0 that con ict with the bound variables of the type scheme.Lemma 4 (Strengthening) If; ; 0 ` ; 0 e : ,FTV( ; ; ) dom( ), anddom( 0) \ FV(e) = ;,then ; ` e : .This lemma could easily be generalized to strengthen the location type assumptions, as well, but this isunnecessary.Proof: It is proved by simple structural induction on the type derivation, using Ground Type Substitutionto eliminate any extra type variables occurring only in the mediating types in (:=D), (APPD), and (LETD).For the most di cult case, (LETD), inversion of the derivation provides a 0 and 0 such that; ; 0 ` ; 0; 0 e1 : 0; ; 0[x : 8 0: 0] ` ; 0 e2 :NonCrit 0(dom( 0)) Weaker ; 0((FTV( 0) \ dom( ; 0)) FTV( ; ; 0); 0)Without loss of generality, assume by -renaming on values, that x 62 dom( 0).Induction cannot be used yet, since FTV( 0) is not necessarily a subset of dom( ; 0). So, de ne S to bea ground type substitution on the type variables in dom( 0) \ FTV( 0). Then, Ground Type Substitutiongives; ; S( 0) ` ; 0; 0 e1 : S( 0); ; S( 0)[x : S(8 0: 0)] ` ; 0 e2 :And S(8 0: 0) = 8 0:S( 0) since the domains of S and 0 are non-intersecting. Induction then applies,and the conclusion follows by (LETD).2Lemma 5 (Type Substitution) If; `( ; 1; 0)+c0 e : ,16 S = [ 1 7! 1; . . . ; n 7! n],for all 1 i n, SWeaker( ;2)+c(FTV( i); 1( i)), andWeaker (FTV( ; ; ) \ dom( ); 0),then there exists 0 1 such that S( );S( ) `((( 0; 2)+c); 0)+c0 e : S( ).Proof: This is proved by structural induction on the typing derivation. The (LOCD) and (UNITD) caseshold trivially with the de nition 0 = .The (VARD) case requires careful treatment of the domains of substitutions to show that instanti-ation is stable under type substitution. Inversion of the type derivation states that the instantiation`( ; 0; 1)+c0 (x) holds. LetS = [ 1 7! 1; . . . ; n 7! n]where 1; . . . ; k 62 BTV( (x)), and where k+1; . . . ; n 2 BTV( (x)). By the de nition of the instantiationrelation,(x) = 8[ k+1 7! s1; . . . ; k+m 7! sm]: 0where k +m n, and there exists types 01; . . . ; 0m such that de ning the type substitutionS1 = [ k+1 7! 01; . . . ; k+m 7! 0m]implies S1( 0) = . In particular, choose S1 so that, for 1 j m, if k+j 62 FTV( 0), then 0j is ground,so that FTV(rng(S1)) FTV( ). In addition, de ne the following type substitutions, where 001; . . . ; 00n arenew:S 0 = [ 1 7! 1; . . . ; k 7! k]S2 = [ 001 7! S( 01); . . . ; 00m 7! S( 0m)]S3 = [ k+1 7! 001 ; . . . ; k+m 7! 00m]Thus, S( (x)) = 8[ 001 7! s1; . . . ; 00m 7!sm]:S0(S3( 0)), and S2(S 0(S3( 0))) = S(S1( 0)) = S( ). Now de ne0 so that for all 2 dom( 0) = dom( ),0( ) =( ) +min(0; c) if 2 FTV(rng(S1))( )otherwiseBy the last assumption, and since FTV(rng(S1)) FTV( ), then 0 1 . And since by instantiation, forall 1 j m, SWeaker( ; 1; 0)+c0 (FTV( 0j); sj), the third assumption implies that, for all 1 j m,SWeaker((( 0; 2)+c); 0)+c0 (FTV(S( 0j)); sj). Thus, the desired instantiation holds,`((( 0; 2)+c); 0)+c0 S( (x)) S( )and the conclusion holds by (VAR).The (!D) and (LAMD) cases follow simply by induction. Both the (:=D) and (APPD) cases must also useGround Type Substitution, while in the (REFD), (APPD), and (LETD) cases, an appropriate 0 must becalculated to satisfy the side conditions, as in the (VARD) case. For example, in the (APPD) case, inversiongives a 0 such that; `( ; 1; 0)+c0+1 e1 : 0!; `( ; 1; 0)+c0 e2 : 0 Weaker( ; 1; 0)+c0(FTV( 0);0)To allow the last assumption to hold inductively, the type variables occurring only in the mediating type 0must be removed. So, de ne a ground type substitution S 0 over the type variables in (dom( )\FTV( 0))FTV( ; ; ). By Ground Type Substitution,; `( ; 1; 0)+c0+1 e1 : S 0( 0)!; `( ; 1; 0)+c0 e2 : S 0( 0)17 Since Weaker (FTV(S 0( 0)) \ dom( ); 0), induction proves that there exists 00 1 and 000 1 suchthatS( );S( ) `((( 00; 2)+c); 0)+c0+1 e1 : S(S 0( 0)! ) S( );S( ) `((( 000; 2)+c); 0)+c0 e2 : S(S 0( 0))and let 0000 = min( 00; 000). Now the side condition of (APPD) must be satis ed. To this end, de ne 0 sothat for all 2 dom( 0) = dom( ),0( ) =0000( ) +min(0; c) if 2 FTV(S 0( 0))0000( )otherwiseSo that by the original side condition and the third assumption, the new side condition holds:Weaker((( 0; 2)+c); 0)+c0(FTV(S(S 0( 0)));0)Also, by the original side condition and the last assumption, 0 1 0000. So, the conclusion holds by Weak-ening and the (APPD) rule.2Lemma 6 (Value Substitution) If; ` ; 1 v : 1,; [x : 8 1: 1] `( ; 2)+c e : 2,dom( ) dom( ), andWeaker (FTV( ; 1) \ dom( );0),then there exists 0 1 such that ; `( 0; 2)+c [v=x]e : 2.Proof: The proof is by structural induction on the type derivation for e. The (LOCD), (UNITD), andwhen e 6= x, (VARD) cases follow from Strengthening with the de nition 0 = . When e = x, then`( ; 2)+c 8 1: 12 follows by inversion. By the de nition of instantiation, there is a type substitution Ssuch that S( 1) = 2, and for all 0 2 dom(S), SWeaker( ;2)+c(FTV(S( 0)); 1( 0)). Also, S( ) = . Theconclusion holds by Type Substitution and Strengthening.The (REFD), (!D), and (LAMD) cases hold by induction. The (:=D) and (APPD) cases hold by inductionand Weakening. In the (LETD) case, inversion states that there exists a 0 and 0 such that; [x : 8 1: 1] `(( ; 2)+c); 0 e1 : 0; [x : 8 1: 1; y : 8 0: 0] `( ; 2)+c e2 : 2NonCrit 0(dom( 0)) Weaker( 0; 2)+c((FTV( 0) \ dom( ; 2)) FTV( ; [x : 8 1: 1]);0)By -Renaming Type Substitution, we can assume that the type variables in 0 do not clash with those in1. So, by induction, there exists 00 1 and 000 1 such that; `(( 00; 2)+c); 0 [v=x]e1 : 0; [y : 8 0: 0] `( 000; 2)+c [v=x]e2 : 2Let 0000 = min( 00; 000). In order to satisfy the last side condition of (LETD), de ne 0 so that for all2 dom( 0) = dom( ),0( ) = min( 0000( ); c) if 2 FTV( 1)0000( )otherwiseBy the last assumption, 0 1 , and Weaker0+c(FTV(8 1: 1);0). So,Weaker( 0; 2)+c((FTV( 0) \ dom( ; 2)) FTV( ; ); 0)and the conclusion holds by Weakening and (LETD).2Theorem 1 (Type Preservation Under Evaluation) If18 ` e =) v; 0,; ` e : ,` +c : ,c 0, andCrit +c(FTV( )),then there exists 0 and 0 such that0 1; 0; ` 0 v : ,` 0+c 0 : ; 0, andCrit 0(FTV( 0))Proof: The proof is by structural induction on the evaluation derivation. The constant c correspondsexactly with the abstraction depth of the algorithmic formalisms, so the strength context + c is that ofthe top-level. Note that the type judgments in the assumption and conclusion use strength contexts thatare not adjusted by c. Since the location type assumption and strength context are extended and weakenedfor each sub-derivation, the weakening lemma is needed to prove the assumptions of many induction cases.The (VAL) case holds with 0 = and 0 = , since 0 = .For the (ALLOC) case, inversion of the rst two assumptions gives` e =) v; 10 = 1[l 7! v]; ` e : 0 Crit (FTV( ))where = 0 ref. So, induction provides a 1 and 0 such that0 1; 1; ` 0 v : ` 0+c 1 : ; 1 Crit 0+c(FTV( 1))De ning 0 = 1[l : ], then ` 0+c 0 : ; 0. And ; 0; ` 0 l : ref holds by (LOC). And by Weakeningand the de nition of type matching, then ` 0+c 0 : ; 0. Since FTV( 0) = FTV( 1; ), the conclusionthen holds.In the (CONT) case, inversion gives; ` e : ref ` e =) l; 0where v = 0(l). Induction then proves that there exists a 0 and 1 such that1 1; 0; ` 1 l : ref ` 1+c 0 : ; 0 Crit 1(FTV( 0))So, ; 0(l) = . Then, by the de nition of type matching and Strengthening, ; 0; ` 1+c v : . De ne0 so that for all 2 dom( 0) = dom( ),0( ) =1( ) + c if 2 FTV( ; 0)1( )otherwiseSince Crit 1(FTV( ; 0)), then 0 1 . The type judgments of the conclusion then follow by Strengtheningand Weakening, since c 0.The (UPD), (APPLY), and (BIND) cases are similar, with a pattern of induction followed by weakening.The latter two also use Value Substitution to allow induction on the result of substitution. Because of thesimilarities, only the (APPLY) case is given here. 19 For (APPLY), inversion gives a 2 such that` e1 =) fn x)e01; 11 ` e2 =) v2; 22 `[v2=x]e01 =) v; 0; ` +1 e1 : 2!; ` e2 : 2 Weaker (FTV( 2); 0)Induction on the derivation involving e1 shows that there exists a 1 and 1 such that1 + 1 1 + 1; 1; ` 1+1 fn x)e01 : 2!` 1+1+(c 1) 1 : ; 1 Crit 1+1(FTV( 1))Weakening proves ; 1; ` 1 e2 : 2 so that induction applies, giving a 2 and 2 such that2 1 1; 1; 2; ` 2 v2 : 2 ` 2+c 2 : ; 1; 2 Crit2(FTV( 2))De ne 3 so that for all 2 dom( 3) = dom( 2),3( ) = min( 2( );0) if 2 FTV( )2( )otherwiseThus, 3 1 2 and Weaker 3(FTV( ; 1; 2; 2); 0). Inversion on the function value, along with Weaken-ing, proves; 1; 2; [x : 2] ` 3 e01 :; 1; 2; ` 3 v2 : 2So, using the trivial generalization 8 : 2 = 2. Value Substitution proves that there exists 4 1 3 such that; 1; 2; ` 4 [v2=x]e01 : . Since c 0, then Crit 4+c(FTV( ; 1; 2)). Induction applies again, giving a3 and 0 such that0 1 4; 1; 2; 3; ` 0 v : ` 0+c 0 : ; 1; 2; 3 Crit 0(FTV( 3))The conclusion then holds with 0 = 1; 2; 3.220

برای دانلود متن کامل این مقاله و بیش از 32 میلیون مقاله دیگر ابتدا ثبت نام کنید

ثبت نام

اگر عضو سایت هستید لطفا وارد حساب کاربری خود شوید

منابع مشابه

Weak Polymorphism Can Be

The weak polymorphic type system of Standard ML of New Jersey (SML/NJ) (MacQueen, 1992) has only been presented as part of the implementation of the SML/NJ compiler, not as a formal type system. As a result, it is not well understood. And while numerous versions of the implementation have been shown unsound, the concept has not been proved sound or unsound. We present an explanation of weak pol...

متن کامل

Object-Oriented Programming and Standard ML

This paper explores connections between object-oriented programming and Standard ML. In particular we show that F-bounded polymorphism can be expressed using ML's polymorphism and a programming technique we call wrapping. The encoding of F-bounded polymorphism can be used to encode classes as ML modules.

متن کامل

Standard ML-NJ weak polymorphism and imperative constructs

Standard ML of New Jersey (SML-NJ) uses \weak type variables" to restrict the polymorphic use of functions that may allocate reference cells, manipulate continuations, or use exceptions. However, the type system used in the SML-NJ compiler has not previously been presented in a form other than source code nor proved correct. We present a set of typing rules, based on a careful analysis of the c...

متن کامل

Relaxing the Value Restriction

Restricting polymorphism to values is now the standard way to obtain soundness in ML-like programming languages with imperative features. While this solution has undeniable advantages over previous approaches, it forbids polymorphism in many cases where it would be sound. We use a subtyping based approach to recover part of this lost polymorphism, without changing the type algebra itself, and t...

متن کامل

A Syntactic Approach to Type Soundness

We present a new approach to proving type soundness for Hindley/Milner-style polymorphic type systems. The keys to our approach are (1) an adaptation of subject reduction theorems from combinatory logic to programming languages, and (2) the use of rewriting techniques for the speciication of the language semantics. The approach easily extends from polymorphic functional languages to imperative ...

متن کامل

Three comments on the anti-frame rule

It is well-known that a careless combination of parametric polymorphism and weak references is unsound. (A weak reference is one that can be read and written without restrictions, as in ML.) The standard way to work around this problem is to rely on the value restriction [7] that is, to restrict the ∀-introduction rule to values (as opposed to arbitrary terms). Charguéraud and Pottier [3] point...

متن کامل

ذخیره در منابع من


  با ذخیره ی این منبع در منابع من، دسترسی به آن را برای استفاده های بعدی آسان تر کنید

برای دانلود متن کامل این مقاله و بیش از 32 میلیون مقاله دیگر ابتدا ثبت نام کنید

ثبت نام

اگر عضو سایت هستید لطفا وارد حساب کاربری خود شوید

عنوان ژورنال:

دوره   شماره 

صفحات  -

تاریخ انتشار 1993